Kwik.Page.include("Kwik.Ui.Controls.Control.js");
Kwik.Page.include("Kwik.Collections.Hashtable.js");
Kwik.Page.include("Kwik.Dom.Utility.js");
Kwik.Page.include("Kwik.Ui.Css.js");
Kwik.Page.include("Kwik.Ui.Utility.js");

/** 
* Menu control for displaying clickable items
* @constructor
* @extends Kwik.Ui.Controls.Control
* @requires Kwik.Ui.Controls.MenuItem
* @requires Kwik.Ui.Controls.Control
* @requires Kwik.Collections.Hashtable
* @requires Kwik.Dom.Utility
* @created 11:07 AM 8/4/2009
* @modified 11:07 AM 8/4/2009
*/
Kwik.Ui.Controls.Menu = function(config)
{
	/** @ignore */
	Kwik.Utility.extend(this, "Kwik.Ui.Controls.Control");
	this.__class.push("Kwik.Ui.Controls.Menu");

	/** Reference to it's parent object @type Kwik.Ui.Controls.MenuItem */
	this.parent = null;
	/** Collection of items in this menu @type Kwik.Ui.Controls.MenuItemCollection */
	this.items = new Kwik.Ui.Controls.MenuItemCollection({parent:this});

	/** Load this menu from an element */
	this.load = function Menu_load(element)
	{
		this.Kwik$Ui$Controls$Control.load(element);
		var items = Kwik.Dom.Utility.getChildElements(element, "div", "Item");
		items = items.concat(Kwik.Dom.Utility.getElementsByAttribute(element, "kwikclass", "Kwik.Ui.Controls.MenuItem"));

		for(var i=0; i<items.length; i++)
		{
			var item = new Kwik.Ui.Controls.MenuItem();
			item.load(items[i]);
			this.items.add(item);
		}
	};

	/** Configure this menu @type Kwik.Ui.Controls.MenuConfig */
	this.configure = function Menu_configure(config)
	{
		config = this.Kwik$Ui$Controls$Control.configure(config);
		if(config.parent){this.parent = config.parent;}
		if(config.mousefocus === true)
		{
			this.attachEvent("onmouseover", this._mouseOver);
			this.attachEvent("onblur", this._blur);
		}
		if(config.mousefocus === false)
		{
			this.detachEvent("onmouseover", this._mouseOver);
			this.detachEvent("onblur", this._blur);
		}
		return config;
	};

	/** Event handler for onblur events, deactivates all items, used when mousefocus is set to true */
	this._blur = function Menu__blur()
	{
		if(this.items.active != null){this.items.active.deactivate();}
	};

	/** Event handler for mouseover events which sets focus on the element, used when mousefocus is set to true */
	this._mouseOver = function Menu__mouseOver()
	{
		if(this.element.tabIndex){this.element.tabIndex = 0;}
		this.element.focus();
	};

	/** @ignore */
	this.main = function(config)
	{
		if(config){this.configure(config);}
	}; this.main(config);
};

/** 
* Menu control configuration object
* @constructor
* @created 11:07 AM 8/4/2009
* @modified 11:07 AM 8/4/2009
*/
Kwik.Ui.Controls.MenuConfig = function()
{
	/** Reference to it's parent object @type Kwik.Ui.Controls.MenuItem */
	this.parent = null;
	/** When set to true the menu will get focus when the mouse hovers over it and it will deactivate all items when it looses focus @type Boolean */
	this.mousefocus = false;
};

/** 
* Clickable menu item, the menu item is activated when the mouse hovers over it. 
* When active it displays it's menu when set.
* @constructor
* @extends Kwik.Ui.Controls.Control
* @requires Kwik.Ui.Controls.Menu
* @requires Kwik.Ui.Controls.MenuItemCollection
* @requires Kwik.Ui.Controls.Control
* @requires Kwik.Dom.Utility
* @requires Kwik.Ui.Css
* @requires Kwik.Type
* @created 11:07 AM 8/4/2009
* @modified 11:07 AM 8/4/2009
*/
Kwik.Ui.Controls.MenuItem = function(config)
{
	/** @ignore */
	Kwik.Utility.extend(this, "Kwik.Ui.Controls.Control");
	this.__class.push("Kwik.Ui.Controls.MenuItem");

	/** Reference to it's parent object @type Kwik.Ui.Controls.MenuItemCollection */
	this.parent = null;
	/** Reference to a menu object which will be shown when the mouse hovers over this object @type Kwik.Ui.Controls.Menu */
	this.menu = null;
	/** The name of this item which is used to identify this item @type String */
	this.name = "";
	/** Indication whether this item is activated or not @type Boolean */
	this.active = false;

	/** Load this menu item from an element */
	this.load = function MenuItem_load(element)
	{
		this.Kwik$Ui$Controls$Control.load(element);
		var menu = Kwik.Dom.Utility.getChildElements(element, "div", "Menu")[0];
		if(!menu){menu = Kwik.Dom.Utility.getElementsByAttribute(element, "kwikclass", "Kwik.Ui.Controls.Menu")[0];}

		if(menu)
		{
			Kwik.Page.log.write("Kwik.Ui.Controls.MenuItem.load: Adding menu.");
			Kwik.Ui.Css.removeClassName(menu, "Menu");
			menu.removeAttribute("kwikClass");
			this.menu = new Kwik.Ui.Controls.Menu({parent: this});
			this.menu.load(menu);
		}
	};

	/** Get the array of parent items in hierarchy @type Kwik.Ui.Controls.MenuItem[] */
	this.getParentItems = function MenuItem_getParentItems()
	{
		var ret = [];
		var parent = this.parent;
		while(parent)
		{
			if(Kwik.Type.isKwikType(parent, "Kwik.Ui.Controls.MenuItem"))
			{
				ret.push(parent);
			}
			parent = parent.parent;
		}
		return ret;
	};

	/** Get the array of child items in hierarchy @type Kwik.Ui.Controls.MenuItem[] */
	this.getChildItems = function MenuItem_getChildItems()
	{
		var ret = [];
		if(this.menu)
		{
			var items = this.menu.items.toArray();
			ret = ret.concat(items);

			for(var i=0; i<items.length; i++)
			{
				ret = ret.concat(items[i].getChildItems());
			}
		}
		return ret;
	};

	/** Activate this item and show the menu if set */
	this.activate = function MenuItem_activate()
	{
		if(this.active === true){return;}
		Kwik.Page.log.write("Kwik.Ui.Controls.MenuItem.activate: Activating '" + this.name + "'."); 
		
		var cancel = this.fireEvent("onbeforeactivate");
		if(cancel === true){return;}

		var item = this.parent.activate(this.name);
		if(item == null)
		{
			return;
		}

		this.active = true;

		if(this.menu !== null)
		{
			if(this.menu.element.parentNode === this.element)
			{
				this.menu.close();
				this.menu.open();
			}
			var rect = this.getRectangle();

			this.menu.move(rect.x + rect.w, rect.y);
			this.menu.show();
		}
		this.fireEvent("onactivate");
	};

	/** Deactivate this item and hide the menu if set */
	this.deactivate = function()
	{
		if(this.active === false){return;}
		Kwik.Page.log.write("Kwik.Ui.Controls.MenuItem.deactivate: Deactivating '" + this.name + "'."); 

		var cancel = this.fireEvent("onbeforedeactivate");
		if(cancel === true){return;}

		this.active = false;
		if(this.menu)
		{
			var items = this.getChildItems();
			for(var i=0; i<items.length; i++)
			{
				items[i].deactivate();
			}
			this.menu.hide();
		}
		this.fireEvent("ondeactivate");
	};

	/** Event handler for mouseover events, activates this item when the mouse hovers over it */
	this._mouseOver = function(evt)
	{
		this.activate();
	};

	/** Configure this menu item object @type Kwik.Ui.Controls.MenuItemConfig */
	this.configure = function MenuItem_configure(config)
	{
		config = this.Kwik$Ui$Controls$Control.configure(config);
		if(config.parent){this.parent = config.parent;}
		if(config.menu){this.menu = config.menu;}
		if(Kwik.Type.isString(config.name)){this.name = config.name;}
		if(this.name.length == 0 && this.element.id != ""){this.name = this.element.id;}
		if(this.name.length == 0 && this.element.name != ""){this.name = this.element.name;}
		if(this.name.length == 0){this.name = "MenuItem" + this.ptr.toString();}
		return config;
	};
	
	/** Event fired before this item is activated */
	this.onbeforeactivate = function(){};
	/** Event fired when this item is activated */
	this.onactivate = function(){};
	/** Event fired before this item is deactivated */
	this.onbeforedeactivate = function(){};
	/** Event fired when this item is deactivated */
	this.ondeactivate = function(){};
	
	/** @ignore */
	this.main = function(config)
	{
		if(config){this.configure(config);}
		this.attachEvent("onmouseover", this._mouseOver);

	}; this.main(config);
};

/** 
* Menu item configuration object
* @constructor
* @created 11:07 AM 8/4/2009
* @modified 11:07 AM 8/4/2009
*/
Kwik.Ui.Controls.MenuItemConfig = function()
{
	/** Reference to a parent menu item collection @type Kwik.Ui.Controls.MenuItemCollection */
	this.parent = null;
	/** Reference to a sub menu @type Kwik.Ui.Controls.Menu */
	this.menu = null;
	/** The name of this menu item @type String */
	this.name = null;
};


/** 
* Collection of menu items by name
* @constructor
* @extends Kwik.Collections.Hashtable
* @requires Kwik.Collections.Hashtable
* @requires Kwik.Ui.Controls.Menu
* @requires Kwik.Ui.Controls.MenuItem
* @created 11:07 AM 8/4/2009
* @modified 11:07 AM 8/4/2009
*/
Kwik.Ui.Controls.MenuItemCollection = function(config)
{
	/** @ignore */
	Kwik.Utility.extend(this, "Kwik.Collections.Hashtable");
	this.__class.push("Kwik.Ui.Controls.MenuItemCollection");

	/** Reference to a parent menu @type Kwik.Ui.Controls.Menu */
	this.parent = null;
	
	/** Current active item in the collection @type Kwik.Ui.Controls.MenuItem */
	this.active = null;

	/** Activate an item in the collection @type Kwik.Ui.Controls.MenuItem */
	this.activate = function MenuItemCollection_activate(name)
	{
		var item = this.getItem(name, null);
		if(item != null)
		{
			if(this.active != null)
			{
				this.active.deactivate();
			}
			else
			{
				var items = this.toArray();
				for(var i=items.length-1; i>-1; i--)
					items[i].deactivate(); 
			}
			this.active = item;
		}
		return item;
	};

	/** Add a menu item to this collection @type Kwik.Ui.Controls.MenuItem */
	this.add = function MenuItemCollection_add(item)
	{
		item.parent = this;
		if(item.element.parentNode != this.parent.element)
			this.parent.element.appendChild(item.element);

		if(this.Kwik$Collections$Hashtable.contains(item.name)){this.Kwik$Collections$Hashtable.remove(item.name);}
		this.Kwik$Collections$Hashtable.add(item.name, item);
	};

	/** Remove a menu item from this collection @type Kwik.Ui.Controls.MenuItem */
	this.remove = function MenuItemCollection_remove(name)
	{
		if(name.name){name = name.name;}
		var item = this.Kwik$Collections$Hashtable.remove(name);
		if(item)
		{
			this.parent.element.removeChild(item.element);
			item.parent = null;
		}
		return item;
	};

	/** Remove all items from this collection @type Kwik.Ui.Controls.MenuItem[] */
	this.removeAll = function MenuItemCollection_removeAll()
	{
		var items = this.Kwik$Collections$Hashtable.removeAll();
		for(var i=0; i<items.length; i++)
		{
			this.parent.element.removeChild(items[i].element);
			items[i].parent = null;
		}
		return items;
	};

	/** Configure this menu item collection @type Kwik.Ui.Controls.MenuItemCollectionConfig */
	this.configure = function MenuItemCollection_configure(config)
	{
		config = this.Kwik$Collections$Hashtable.configure(config);
		if(config.parent){this.parent = config.parent;}
		return config;
	};
	
	/** @ignore */
	this.main = function(config)
	{
		if(config){this.configure(config);}
	};this.main(config);
};

/** 
* Configuration object for the Kwik.Ui.Controls.MenuItemCollection object
* @constructor
* @created 11:07 AM 8/4/2009
* @modified 11:07 AM 8/4/2009
*/
Kwik.Ui.Controls.MenuItemCollectionConfig = function()
{
	/** Reference to a parent menu @type Kwik.Ui.Controls.Menu */
	this.parent = null;
};